package com.tianji.learning.task;

import com.tianji.common.utils.CollUtils;
import com.tianji.learning.constants.RedisConstants;
import com.tianji.learning.domain.po.PointsBoard;
import com.tianji.learning.domain.po.PointsBoardSeason;
import com.tianji.learning.service.IPointsBoardSeasonService;
import com.tianji.learning.service.IPointsBoardService;
import com.tianji.learning.utils.TableInfoContext;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;

import static com.tianji.learning.constants.LearningConstants.POINTS_BOARD_TABLE_PREFIX;

/**
 * @description:
 * @author: ajie
 * @date: 2024/5/16 16:59:25
 * @version: 1.0
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class PointsBoardPersistentHandler {

    private final IPointsBoardSeasonService pointsBoardSeasonService;
    private final IPointsBoardService pointsBoardService;
    private final StringRedisTemplate redisTemplate;

    
    /**
     * @description: 创建上赛季（上个月）榜单} 
     * @params: []       
     * @return: 
     * @author: ajie
     * @date: 2024/5/16 17:02
     */
//    @Scheduled(cron = "0 0 3 1 * ?")//每个月1号凌晨3点运行 单机版 定时任务调度
//    @Scheduled(cron = "0 15 11 17 5 ?")//测试
    @XxlJob("createTableJob")
    public void createPointsBoardTableOfLastSeason(){
        log.debug("创建上赛季榜单任务执行了");

        //获取上个月当前时间
        LocalDate time = LocalDate.now().minusMonths(1);

        //查询赛季表获取赛季id 运行条件 begin_time <= time and end_time >= time
        PointsBoardSeason one = pointsBoardSeasonService
                .lambdaQuery()
                .le(PointsBoardSeason::getBeginTime, time)
                .ge(PointsBoardSeason::getEndTime, time)
                .one();
        log.debug("上赛季消息 {}",one);
        if (one == null){
            return;
        }

        //创建上赛季榜单表 points_board_7
        pointsBoardSeasonService.createPointsBoardLatestTable(one.getId());
    }

    //持久化上赛季（上个月）排行榜数据 到db中
    @XxlJob("savePointsBoard2DB")//任务名字要和 xxl-job控制台 任务的jobhandler值保持一致
    public void savePointsBoard2DB(){
        log.debug("持久化上赛季（上个月的）排行榜数据 到db中 任务执行了");
        //获取上个月当前时间
        LocalDate time = LocalDate.now().minusMonths(1);

        //查询赛季表获取赛季id 运行条件 begin_time <= time and end_time >= time
        PointsBoardSeason one = pointsBoardSeasonService
                .lambdaQuery()
                .le(PointsBoardSeason::getBeginTime, time)
                .ge(PointsBoardSeason::getEndTime, time)
                .one();
        log.debug("上赛季消息 {}",one);
        if (one == null){
            return;
        }
        //计算动态表名 并存入threadlocal中
        String tableName = POINTS_BOARD_TABLE_PREFIX + one.getId();
        log.debug("动态表名为 {}",tableName);
        TableInfoContext.setInfo(tableName);

        //分页获取redis中上赛季积分排行榜数据
        String format = time.format(DateTimeFormatter.ofPattern("yyyyMM"));
        String key = RedisConstants.POINTS_BOARD_KEY_PREFIX + format;//board:上赛季的年月 board:202404

        int shardIndex = XxlJobHelper.getShardIndex();//当前分片的索引 从0开始
        int shardTotal = XxlJobHelper.getShardTotal();//总分片数

        int pageNo = shardIndex + 1;//页码
        int pageSize = 1000;
        while (true){
            List<PointsBoard> pointsBoardList = pointsBoardService.queryCurrentBoard(key, pageNo, pageSize);
            if (CollUtils.isEmpty(pointsBoardList)){
                break;//跳出循环，进行下一步
            }
            pageNo+=shardTotal;
            //持久化到db相应的赛季表中 批量新增
            for (PointsBoard board : pointsBoardList) {
                board.setId(Long.valueOf(board.getRank()));//历史赛季排行榜中的id 就代表了排名
                board.setRank(null);//使用动态表名插件，没有的列必须为null
            }
            pointsBoardService.saveBatch(pointsBoardList);
        }
        //清空threadlcoal中的数据
        TableInfoContext.remove();
    }

    @XxlJob("clearPointsBoardFromRedis")
    public void clearPointsBoardFromRedis(){
        //获取上个月时间
        LocalDate time = LocalDate.now().minusMonths(1);
        String format = time.format(DateTimeFormatter.ofPattern("yyyyMM"));
        String key = RedisConstants.POINTS_BOARD_KEY_PREFIX + format;//board:上赛季的年月 board:202404
        //删除
        redisTemplate.unlink(key);
    }
}